#include "VxIrrLib.h"
#include "../irrlicht/CColorConverter.h"

#include <VxUtilLib/VxColorUtil.h>

//------------------------------------------------------------------------------
//! load picture to Texture in ARGB (ECF_A8R8G8B8) format
irr::video::ITexture * getARGBTexture( irr::video::IVideoDriver * poDriver, irr::core::stringc filename )
{
	irr::video::IImage* newImage = getARGBImage( poDriver, filename); 
	if( newImage )
	{
		irr::video::ITexture* newTexture = poDriver->addTexture(filename, newImage); 
		return newTexture;
	}
	return NULL;
}

//------------------------------------------------------------------------------
//! load picture to image in ARGB (ECF_A8R8G8B8) format
irr::video::IImage * getARGBImage( irr::video::IVideoDriver * poDriver, irr::core::stringc filename ) 
{ 
	irr::video::IImage* srcImage = poDriver->createImageFromFile(filename); 
	irr::video::IImage* bmpImage = NULL; 

	if( srcImage->getColorFormat() != irr::video::ECF_A8R8G8B8 ) 
	{ 
		log_msg( 0, "getARGBImage: Image %s color format doesn't match, converting!\n", filename.c_str()); 
		irr::core::dimension2du dim = srcImage->getDimension(); 
		void* load_pixels = malloc((dim.Width * dim.Height) << 2); 
		switch(srcImage->getColorFormat()) 
		{ 
		case irr::video::ECF_A1R5G5B5: 
			irr::video::CColorConverter::convert_A1R5G5B5toA8R8G8B8( srcImage->lock(), (dim.Width * dim.Height), load_pixels ); 
			break; 
		case irr::video::ECF_R5G6B5: 
			irr::video::CColorConverter::convert_R5G6B5toA8R8G8B8( srcImage->lock(), (dim.Width * dim.Height), load_pixels ); 
			break; 
		case irr::video::ECF_R8G8B8: 
			irr::video::CColorConverter::convert_R8G8B8toA8R8G8B8( srcImage->lock(), (dim.Width * dim.Height), load_pixels ); 
			break; 
		} 
		bmpImage = poDriver->createImageFromData(irr::video::ECF_A8R8G8B8, dim, load_pixels, false, true); 
		free(load_pixels); 
		srcImage->drop(); 
		return bmpImage; 
	} 
	else 
	{ 
		return srcImage; 
	} 
}
//------------------------------------------------------------------------------
//! blit image from one texture into another ( both textures must be 32bit format )
//! return percent pixels changed
int BlitTextureOnTexture(	irr::video::ITexture *	poSrcTexture,		// texture to use as source image ( must be A8R8G8B8 fromat )
							U32						u32DestXPos,		// left pixel of destination image to blit to
							U32						u32DestYPos,		// top pixel of destination image to blit to
							irr::video::ITexture *	poDestTexture,		// texture to blit onto ( must be A8R8G8B8 fromat )
							BOOL					bWrap,				// if true then if blit goes past edge of destination image then wrap to other side
							U32						u33ExcludeLowColor, // if u33ExcludeLowColor != u33ExcludeHighColor then exclude copying to dest if
							U32						u33ExcludeHighColor )// color is not between u33ExcludeLowColor and u33ExcludeHighColor
{
	int iPixelsChanged = 0;
	BOOL bHasExclusionColors = (u33ExcludeLowColor == u33ExcludeHighColor)?false:true;
	const irr::core::dimension2d<irr::u32> oDestSize = poDestTexture->getSize();
	U32 u32DestWidth = oDestSize.Width;
	U32 u32DestHeight = oDestSize.Height;
	if( ( u32DestXPos >= u32DestWidth ) || ( u32DestYPos >= u32DestHeight ) )
	{
		log_msg( 1, "BlitTextureOnTexture: destination coords not even on dest texture\n" );
		return iPixelsChanged;
	}


	const irr::core::dimension2d<irr::u32> oSrcSize = poSrcTexture->getSize();
	U32 u32SrcWidth = oSrcSize.Width;
	U32 u32SrcHeight = oSrcSize.Height;

	U32 * pu32SrcPixels = (U32 *)poSrcTexture->lock( irr::video::ETLM_READ_ONLY );
	U32 u32SrcIdx = 0;
	U32 * pu32DestPixels = (U32 *)poDestTexture->lock();
	//memset( pu32DestPixels, 0x7f, sizeof( U32 ) *  u32DestWidth * u32DestHeight );
	for( U32 u32SrcRow = 0; u32SrcRow < u32SrcHeight; u32SrcRow++ )
	{
		// for each src row
		// calculate destination row
		U32 u32DestRowIdx = u32SrcRow + u32DestYPos;
		if( u32DestRowIdx >= u32DestHeight )
		{
			// this row is past end of bitmap.. should we wrap ?
			if( false == bWrap )
			{
				// skip row
				continue;
			}
			else
			{
				u32DestRowIdx = u32DestRowIdx - u32DestHeight;
			}
		}
		U32 u32DestColIdx = u32DestXPos;


		for( U32 u32SrcCol = 0; u32SrcCol < u32SrcWidth; u32SrcCol++ )
		{
			U32 u32SrcColor = pu32SrcPixels[ u32SrcIdx ];
			u32SrcIdx++;

			if( u32DestColIdx >= u32DestWidth )
			{
				// this column is past end of bitmap.. should we wrap ?
				if( false == bWrap )
				{
					// skip rest of row
					break;
				}
				else
				{
					u32DestColIdx = u32DestColIdx - u32DestWidth;
				}
			}
			U32 u32DestArrayIdx = ( u32DestRowIdx *  u32DestWidth ) + u32DestColIdx;
			u32DestColIdx++;
			U32 u32DestColor = pu32DestPixels[ u32DestArrayIdx ];
			
			if( bHasExclusionColors )
			{
				// check if is a color we dont want to copy to
				if( (( u32DestColor & 0xff ) >= (u33ExcludeLowColor & 0xff )) &&
					(( u32DestColor & 0xff00 ) >= (u33ExcludeLowColor & 0xff00 )) &&
					(( u32DestColor & 0xff0000 ) >= (u33ExcludeLowColor & 0xff0000 )) &&
					(( u32DestColor & 0xff ) <=  (u33ExcludeHighColor & 0xff )) &&
					(( u32DestColor & 0xff00 ) <= (u33ExcludeHighColor & 0xff00 )) &&
					(( u32DestColor & 0xff0000 ) <= (u33ExcludeHighColor & 0xff0000 )) )
				{
					//color is in the exclusion range
					continue;
				}
			}
			// not excluded so blend 
			pu32DestPixels[ u32DestArrayIdx ] = VxBlendColors( u32SrcColor, pu32DestPixels[ u32DestArrayIdx ] );
			iPixelsChanged++;
			
			//pu32DestPixels[ u32DestArrayIdx ] = pu32DestPixels[ u32DestArrayIdx ] & 0x133f3f3f;
			//if( 0 != ( u32SrcColor & 0xff000000 ) )
			//{
			//	pu32DestPixels[ u32DestArrayIdx ] = u32SrcColor;
			//}
		}
	}
	poSrcTexture->unlock();
	poDestTexture->unlock();
	return ( iPixelsChanged * 100 )/( u32SrcHeight * u32SrcWidth );
}
